% !TeX program = xelatex 
\documentclass[xcolor=svgnames,10pt,UTF8]{ctexbeamer}
%\documentclass[aspectratio=169,xcolor=svgnames,10pt]{beamer}

\RequirePackage{slide}

%\logo{\includegraphics[scale=0.015]{../figure/logo.jpg}}
\title{SystemVerilog芯片验证}
\subtitle{第3章~结构化过程}
%\author{王旭}
%\institute{深圳信息职业技术学院~微电子学院}
\date{\today}

\begin{document}

\frame{\titlepage}
%\LogoOn
%\LogoOff

\section{initial和always过程} \label{initial and always procedure}

\begin{frame}[t,fragile]{结构化过程}
	\begin{enumerate}
		\item initial过程，使用关键字initial表示。
		\item always过程，使用关键字always、always\_comb、always\_latch和always\_ff表示。
		\item final过程，使用关键字final表示。
		\item 任务（task）。
		\item 函数（function）。
	\end{enumerate}

	\begin{enumerate}
		\item initial和always过程在仿真开始时启动。
		\item initial过程只被执行一次，当内部语句结束时它就停止运行。
		\item always过程不断被重复执行，只有当仿真结束时，它才停止运行。
		\item initial和always过程之间不应该有隐含的执行顺序，
		\item initial过程通常用于生成时钟和复位激励。
	\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{always\_comb过程描述组合电路}

	\begin{enumerate}
		\item always\_comb过程没有敏感列表，它可以避免由于敏感信号列表不全所生成的锁存器。
		\item always\_latch过程描述锁存器，它也不需要添加敏感信号列表。
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch3/sec1/1/dut.sv}

\end{frame}

\begin{frame}[t,fragile]{always\_ff过程描述时序逻辑}

	\begin{enumerate}
		\item always\_ff过程需要添加边沿触发的敏感信号列表。
		\item always\_ff过程只包含一个事件控件，always\_ff过程中被赋值的变量不能在块外被再次赋值。
	\end{enumerate}


\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]
{src/ch3/sec1/2/dut.sv}

\end{frame}

\section{运算符和过程语句} \label{Procedural Statements}

\begin{frame}[t,fragile]{运算符和过程语句}

	\begin{enumerate}
		\item for语句中定义局部循环变量
		\item ++、--、+=和\&=
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch3/sec2/1/test.sv}

\begin{lstlisting}
sum=45
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{continue和break语句}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch3/sec2/2/test.sv}

\begin{lstlisting}
i=4
i=5
i=6
i=7
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{case语句和inside操作符}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]
{src/ch3/sec2/3/test.sv}

\end{frame}

\section{任务和函数} \label{Tasks, Functions}

\subsection{任务和函数的特点} \label{features of task and function}

\begin{frame}[t,fragile]{任务和函数的共同点}

\begin{enumerate}
	\item 任务和函数可以在module、package等块内定义，可以被多次调用。
	\item 任务和函数中只能使用行为级语句，不能使用always和initial过程。
	\item 设计者可以在always和initial过程中调用任务和函数。
	\item 任务和函数中不能定义wire类型的变量，它们的输入和输出参数默认是寄存器类型。
	\item 任务和函数默认是静态（static）的，它们内部定义的变量也是静态的。即使任务或函数被多次调用，它们仍然共享相同的局部静态变量。这类似于吃饭时所有人（被多次调用的函数或任务）都共用白色的公筷（静态局部变量）。
	\item 当任务和函数被声明为自动类型时，每次被调用的任务或函数都有独立的自动局部变量。这类似于吃饭时每个人（被多次调用的函数或任务）都有自己黑色的私筷（自动局部变量）。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{任务和函数的共同点}

任务和函数的主要区别如下。

\begin{enumerate}
	\item 任务可以包含时序控制而函数不能。
	\item 任务可以调用其他任务或函数，而函数只能函数，不能调用任务。
	\item 任务可以访问它所在的module中的信号。
\end{enumerate}

不消耗时间的任务应该被定义为没有返回值的void函数。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
function void print();
	$display("a=%0d, b=%0d, sum=%0d", a, b, sum);
endfunction
\end{lstlisting}

使用void'忽略函数返回值。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch3/sec3/1/test.sv}

\end{frame}

\subsection{例程声明的简化}

\subsection{例程参数的引用传递} \label{Advanced Argument Types}

\begin{frame}[t,fragile]{例程的值传递和引用传递}

任务和函数统称为例程，例程的定义可以采用 C 语言的形式。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-20},consecutivenumbers=false]
{src/ch3/sec3/2/test.sv}

\end{frame}

\begin{frame}[t,fragile]{例程的值传递和引用传递}

	\begin{enumerate}
		\item 引用传递时例程的形参是ref类型，这时形参实际是实参的别名，两者指向相同的地址空间。
		\item 引用传递在静态类型的例程中可能会出错，推荐只在自动类型的例程中使用引用传递。
	\end{enumerate}

\begin{lstlisting}
in test, a=0
in task, a=1
in task, a=2
in test, a=2
\end{lstlisting}

\begin{lstlisting}
in test, a=0
in task, a=1
in test, a=1
in task, a=2
in test, a=2
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{模块中的任务}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-20},consecutivenumbers=false]
{src/ch3/sec3/3/test.sv}

\end{frame}

\begin{frame}[t,fragile]{const ref类型}

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
function automatic void print(const ref bit [3:0] a[]);
	foreach(a[i]) $display("%0d", a[i]);
endfunction
\end{lstlisting}

\end{frame}

\subsection{例程参数的默认值} \label{Default Value for an Argument}

\begin{frame}[t,fragile]{例程参数的默认值}

数组的部分元素求和，参数lo和hi带有默认值0，表示数组的上下边界。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-21},consecutivenumbers=false]
{src/ch3/sec3/4/test.sv}

\end{frame}

\section{静态例程和自动例程} \label{static and automatic procedure}

\begin{frame}[t,fragile]{静态例程}

\begin{enumerate}
	\item module、interface和package默认都使用静态存储，它们内部的例程也是静态的。
	\item 静态例程的所有实例共享该例程中的全部静态成员。
	\item automatic module中定义的例程是自动存储的，使用关键字static可以在其中定义静态变量。
	\item 静态变量的定义语句会在仿真前执行，所以定义静态变量时只能进行常数值的初始化。
	\item 当然也可以将静态变量的定义和初始化拆分成两条语句，在仿真过程中执行静态变量的初始化。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch3/sec3/5/test.sv}

\end{frame}

\begin{frame}[t,fragile]{自动例程}

\begin{enumerate}
	\item 在定义例程时添加automatic关键字。
	\item 在自动存储的module、interface或package中定义例程。
	\item 自动例程的每个实例都有独立的自动局部数据，因此自动例程支持递归调用。
\end{enumerate}

计算整数阶乘，观察使用和不使用automatic时的运行结果。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]
{src/ch3/sec3/6/test.sv}

\end{frame}

\end{document}